/* 创建通用的下载/导出、导入的工具 */
import axios from 'axios'
import store from '@/store'
import {Message, MessageBox} from 'element-ui'
import {getToken} from '@/utils/auth'

// create an axios instance
const service = axios.create({
  // 设置响应的默认类型，arraybuffer为二进制数组
  responseType: 'arraybuffer'
})

// 请求拦截器
service.interceptors.request.use(
  config => {
    if (store.getters.token) {
      // 为本次下载请求的请求头添加Authorization字段，其字段值为token令牌
      config.headers['Authorization'] = getToken()
    }
    return config
  },
  error => {
    console.log(error) // for debug
    return Promise.reject(error)
  }
)

// 响应拦截器
service.interceptors.response.use(
  resp => {
    try {
      // 参考帖子：https://www.cnblogs.com/mingyeliu/p/15357753.html
      // 上面第11行将响应类型设置为 responseType: 'arraybuffer'，二进制数组
      // 请求成功时，后端返回文件流(二进制数组格式)，正常导出文件;
      // 请求失败时，后端返回json对象，如：{"code":403,"message":"权限不足，请联系管理员！"}，也被转成了arraybuffer
      // (请求失败场景一：在导出的API接口上加入@PreAuthorize("hasAuthority('/employee/basic/exportDa')")导致没有权限。)
      // 如果出现上述403错误，是无法将JSON对象中的错误信息正确展示。
      // 解决方案：将已转为arraybuffer类型的数据转回Json对象，然后进行判断
      const enc = new TextDecoder('utf-8')
      const res = JSON.parse(enc.decode(new Uint8Array(resp.data))) // 转化成json对象
      // 如果JSON.parse(enc.decode(new Uint8Array(resp.data)))不报错，说明后台返回的是json对象，则弹框提示
      // 如果JSON.parse(enc.decode(new Uint8Array(resp.data)))报错，说明返回的是文件流，进入catch，执行下载
      if (resp.status && (res.code === 500 || res.code === 401 || res.code === 403)) {
        MessageBox.confirm(res.message, '提示信息', {
          confirmButtonText: '确认',
          cancelButtonText: '取消',
          type: 'warning'
        }).then(() => {
          // 重置token值将重定向到登录页面。
          store.dispatch('user/resetToken').then(() => {
            location.reload()
          })
        })
      }
    } catch (e) {
      // 如果上面转JSON对象报错，则说明后端响应过来的数据是二进制数组格式，则执行下载操作，先得到响应头
      const headers = resp.headers
      // 导入js-file-download插件
      const fileDownload = require('js-file-download')
      // 截取响应头中的filename的值，即文件名
      let fileName = headers['content-disposition'].split(';')[1].split('filename=')[1]
      // 获取响应头中的content-type的值，即内容类型
      const contentType = headers['content-type']
      // 对文件名做格式转换，因为文件名会经常有中文，格式转换是防止中文乱码
      fileName = decodeURIComponent(fileName)
      // 通过js-file-download插件下载我们的文件/导出员工信息
      fileDownload(resp.data, fileName, contentType)
    }
  },
  error => {
    console.log('err' + error) // for debug
    Message({
      message: error.message,
      type: 'error',
      duration: 5 * 1000
    })
    return Promise.reject(error)
  }
)

// 下载通用方法
export const downloadRequest = (url, query) => {
  return service({
    url: url,
    method: 'get', // get请求时，其请求参数名为params，而post请求时，参数名为data
    params: query
  })
}
// 把download.js导出，供其他组件来调用
export default service
